﻿// © Benn Eichhorn 2010
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Algobox.Feeds.Finance.Chix.CHIXMD.Messages
{
    /// <summary>
    /// Singleton Chi-X Order Execution message
    /// </summary>
    public class OrderExecution : IMessage
    {
        private OrderExecution() { }

        private static OrderExecution m_Instance = new OrderExecution();

        /// <summary>
        /// Get's the singleton instance of the OrderExecution class
        /// </summary>
        /// <returns>Current OrderExecution</returns>
        public static OrderExecution GetInstance() { return m_Instance; }

        public char MessageType { get { return 'S'; } }

        /// <summary>
        /// Milliseconds since midnight
        /// </summary>
        public int TimeStampMillis;

        /// <summary>
        /// Slow, calculates current TimeStamp from TimeStampMillis
        /// </summary>
        public DateTime TimeStamp { get { return MessageParser.Date.AddMilliseconds(TimeStampMillis); } }

        /// <summary>
        /// The reference key of the order that was executed
        /// </summary>
        public int OrderReference;

        /// <summary>
        /// The day unique trade reference number
        /// </summary>
        public int TradeReference;

        /// <summary>
        /// The number of shares executed on this trade
        /// </summary>
        public ulong ExecutedShares;


        public override string ToString()
        {
            return String.Format("IMessage->OrderExec: OrderReference={0},TradeReference={1},ExecutedShares={2},TimeStamp={3}", OrderReference, TradeReference, ExecutedShares, TimeStamp);
        }


        // Order Execution
        const int S_E_LEN = 34;
        const int S_E_ORDERREF_LOC = 10;
        const int S_E_ORDERREF_LEN = 9;
        const int S_E_SHARES_LOC = 19;
        const int S_E_SHARES_LEN = 6;
        const int S_E_TRADEREF_LOC = 25;
        const int S_E_TRADEREF_LEN = 9;

        // Order Execution Long
        const int S_e_LEN = 38;
        const int S_e_ORDERREF_LOC = 10;
        const int S_e_ORDERREF_LEN = 9;
        const int S_e_SHARES_LOC = 19;
        const int S_e_SHARES_LEN = 10;
        const int S_e_TRADEREF_LOC = 25;
        const int S_e_TRADEREF_LEN = 9;


        internal static IMessage ParseShort(ref string inbound)
        {
            // get sequenced data message timestamp
            if (!Int32.TryParse(inbound.Substring(MessageParser.S_TIMESTAMP_LOC, MessageParser.S_TIMESTAMP_LEN), out m_Instance.TimeStampMillis))
            {
                Messages.Error message = Messages.Error.GetInstance("Sequenced data message failed to parse TimeStamp millis as Double", inbound);
                return message;
            }

            if (!Int32.TryParse(inbound.Substring(S_E_ORDERREF_LOC, S_E_ORDERREF_LEN), out m_Instance.OrderReference))
            {
                return Messages.Error.GetInstance("OrderExecution failed to parse OrderReference as Int32", inbound); ;
            }
            if (!UInt64.TryParse(inbound.Substring(S_E_SHARES_LOC, S_E_SHARES_LEN), out m_Instance.ExecutedShares))
            {
                return Messages.Error.GetInstance("OrderExecution failed to parse ExecutedShares as Int32", inbound);
            }
            if (!Int32.TryParse(inbound.Substring(S_E_TRADEREF_LOC, S_E_TRADEREF_LEN), out m_Instance.TradeReference))
            {
                return Messages.Error.GetInstance("OrderExecution failed to parse TradeReference as Int32", inbound);
            }

            return m_Instance;
        }


        internal static IMessage ParseLong(ref string inbound)
        {
            // get sequenced data message timestamp
            if (!Int32.TryParse(inbound.Substring(MessageParser.S_TIMESTAMP_LOC, MessageParser.S_TIMESTAMP_LEN), out m_Instance.TimeStampMillis))
            {
                Messages.Error message = Messages.Error.GetInstance("Sequenced data message failed to parse TimeStamp millis as Double", inbound);
                return message;
            }

            if (!Int32.TryParse(inbound.Substring(S_e_ORDERREF_LOC, S_e_ORDERREF_LEN), out m_Instance.OrderReference))
            {
                return Messages.Error.GetInstance("OrderExecution failed to parse OrderReference as Int32", inbound); ;
            }
            if (!UInt64.TryParse(inbound.Substring(S_e_SHARES_LOC, S_e_SHARES_LEN), out m_Instance.ExecutedShares))
            {
                return Messages.Error.GetInstance("OrderExecution failed to parse ExecutedShares as Int32", inbound);
            }
            if (!Int32.TryParse(inbound.Substring(S_e_TRADEREF_LOC, S_e_TRADEREF_LEN), out m_Instance.TradeReference))
            {
                return Messages.Error.GetInstance("OrderExecution failed to parse TradeReference as Int32", inbound);
            }

            return m_Instance;
        }


        /// <summary>
        /// Deep clone
        /// </summary>
        /// <returns></returns>
        public OrderExecution Clone()
        {
            OrderExecution clone = new OrderExecution();
            clone.ExecutedShares = m_Instance.ExecutedShares;
            clone.OrderReference = m_Instance.OrderReference;
            clone.TimeStampMillis = m_Instance.TimeStampMillis;
            clone.TradeReference = m_Instance.TradeReference;
            return clone;
        }
    }
}
